using System;
using System.Drawing;
using Core;
using Core.GameObjects;
using SdlDotNet.Core;
using SdlDotNet.Graphics;
using SdlDotNet.Graphics.Sprites;
using SdlDotNet.Input;
using SpaceTrader.Core;
using SpaceTrader.Core.GameObjects;
using Font=SdlDotNet.Graphics.Font;

namespace Windows
{
    public class GameWindow : IController
    {
        private TextSprite Console;
        private bool ConsoleVisible = false;
        protected Player CpuPlayer = new Player(0, 0);

        private Font Font;
        private TextSprite FPSCounter;
        private Game game;
        protected Player Player = new Player(0, 0);
        private Surface Screen;
        private float Zoom = 1.0f;

        public GameWindow()
        {
            Screen = Video.SetVideoMode(800, 600);
            Video.WindowCaption = "Space Trader";
            Zoom = 0.5f;

            Game = new Game();
            Game.Controllers.Add(this);

            Font = new Font("C:\\Windows\\Fonts\\Arial.ttf", 12);
            Console = new TextSprite(Logger.Instance().LogFile, Font, Color.Red);
            Console.TextWidth = 200;
            Console.MaxLines = 10;

            FPSCounter = new TextSprite("0fps", Font, Color.Red);

            Logger.Instance().LogChanged += new Logger.LogChangedEventHandler(LogChanged);
            Player.Position = new Point(Screen.Width/2, Screen.Height/2);
            Player.Thrust = 1;
            Player.MaxSpeed = 20;

            Game.AddObject(Player);
        }

        #region IController Members

        public Game Game
        {
            get { return game; }
            set { game = value; }
        }

        public void Render()
        {
            Screen.Fill(Color.Black);
            foreach (GameObject Obj in Game.Objects)
            {
                // Do not render objects that are off screen.
                if (Obj.Position.X < Screen.Width/Zoom && Obj.Position.X > 0 && Obj.Position.Y < Screen.Height/Zoom &&
                    Obj.Position.Y > 0)
                {
                    Surface ObjSurf = Obj.Render();
                    ObjSurf = ObjSurf.CreateScaledSurface((double) Zoom);

                    Point BlitPos = Obj.Position;
                    BlitPos.Offset((ObjSurf.Width/2)*-1, (ObjSurf.Height/2)*-1);

                    Vector ScaledPos = new Vector(BlitPos)*new Vector(Zoom, Zoom, 0f);
                    Screen.Blit(ObjSurf, ScaledPos.Point);

                    Logger.Instance().Log("Rendering " + Obj.ToString(), LogLevel.Debug);
                }
            }

            if (ConsoleVisible)
                Screen.Blit(Console, new Point(10, 10));
            Screen.Blit(FPSCounter, new Point(10, Screen.Height - 10 - FPSCounter.Height));
            Screen.Update();
        }

        #endregion

        [STAThread]
        public static void Main()
        {
            GameWindow Window = new GameWindow();
            Window.Run();
        }

        private void LogChanged(object sender, EventArgs e)
        {
            string[] seperators = {"\r\n", "\n"};
            string[] Lines = Logger.Instance().LogFile.Split(seperators, StringSplitOptions.RemoveEmptyEntries);
            string Text = "";

            int StartLine = 0;
            if (Lines.Length > 10)
                StartLine = Lines.Length - 10;
            else
                StartLine = 0;

            for (int i = StartLine; i < Lines.Length; i++)
            {
                Text += Lines[i] + "\n";
            }

            Console.Text = Text;
        }

        public void Run()
        {
            Events.Quit += new EventHandler<QuitEventArgs>(Quit);
            Events.Tick += new EventHandler<TickEventArgs>(Tick);
            Events.KeyboardDown += new EventHandler<KeyboardEventArgs>(KeyboardDown);
            Events.KeyboardUp += new EventHandler<KeyboardEventArgs>(KeyboardUp);
            Events.MouseButtonDown += new EventHandler<MouseButtonEventArgs>(MouseButtonDown);
            Events.Run();
        }

        private void MouseButtonDown(object sender, MouseButtonEventArgs e)
        {
            Point pos = new Point();
            pos.X = (int) (e.X/Zoom);
            pos.Y = (int) (e.Y/Zoom);

            Game.AddObject(new Projectile(pos.X, pos.Y));
        }

        private void KeyboardUp(object sender, KeyboardEventArgs e)
        {
            switch (e.Key)
            {
                case Key.UpArrow:
                    Player.Throttle = 0.0f;
                    break;

                case Key.LeftArrow:
                case Key.RightArrow:
                    Player.RotationSpeed = 0;
                    break;
            }
        }

        private void KeyboardDown(object sender, KeyboardEventArgs e)
        {
            switch (e.Key)
            {
                case Key.C:
                    ConsoleVisible = !ConsoleVisible;
                    break;

                case Key.Space:
                    Player.Position = new Point(Screen.Width/2, Screen.Height/2);
                    Player.Speed = 0;
                    Logger.Instance().Log("Player reset to center.", LogLevel.Info);
                    break;

                case Key.Escape:
                    Events.QuitApplication();
                    break;

                case Key.UpArrow:
                    Player.Throttle = 1.0f;
                    break;

                case Key.LeftArrow:
                    Player.RotationSpeed = -5;
                    break;

                case Key.RightArrow:
                    Player.RotationSpeed = 5;
                    break;
            }
        }

        private void Tick(object sender, TickEventArgs e)
        {
            FPSCounter.Text = e.Fps.ToString() + "fps";
            if (Keyboard.IsKeyPressed(Key.KeypadMinus))
                if (Zoom > 0.0f)
                    Zoom -= 0.01f;

            if (Keyboard.IsKeyPressed(Key.KeypadPlus))
                if (Zoom < 1.0f)
                    Zoom += 0.01f;

            if (Keyboard.IsKeyPressed(Key.LeftControl))
                Game.AddObject(Player.Fire());

            Game.Update();
        }

        private void Quit(object sender, QuitEventArgs e)
        {
            Events.QuitApplication();
        }
    }
}